home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_09_04 / 9n04040a < prev    next >
Text File  |  1991-02-17  |  6KB  |  309 lines

  1.  
  2.  
  3. /* 
  4.  * puzzle.c:  This QNX Windows program creates a
  5.  * moving tile puzzle, with 15 numbered tiles in a 
  6.  * 4 X 4 enclosure.
  7.  * 
  8.  * It is reproduced here by permission of Quantum Software Systems, Ltd
  9.  * of Kanata, Canada.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <windows.h>
  14.  
  15.  
  16. #define RECT_HEIGHT    250
  17. #define RECT_WIDTH    360
  18. #define PANE_BORDER    140
  19.  
  20. #define PANE_HEIGHT    ((rows)*RECT_HEIGHT + 120)
  21. #define PANE_WIDTH    ((rows)*RECT_WIDTH  + 120)
  22. #define CASE(str)    (((str)[0] << 8) | (str)[1])
  23.  
  24. EVENT_MSG    msg;
  25.  
  26. int            rows = 4, max_num;
  27. int         b[20][20], old[20][20];
  28. int            mv;
  29.  
  30. èmain()
  31.     {
  32.     int    go = YES, wid, pid;
  33.  
  34.     /* connect to QWindows */
  35.     if ( !GraphicsOpen (NULL) )
  36.         exit ( -1 );
  37.  
  38.     SetName("Puzzle", NULL);    /* Optional */
  39.  
  40.     pid = PictureOpen ( "pict", NULL, NULL, LIGHT_GRAY, NULL, NULL, NULL );
  41.     PictureHighlightOptions( NULL, 'N', 0, 0 );
  42.  
  43.     init();
  44.     display();
  45.  
  46.     wid = WindowOpen ("Puzzle", PANE_HEIGHT, PANE_WIDTH,
  47.                       "MT480-r;s", NULL, NULL, pid);
  48.  
  49.     /*
  50.      *    Put control button in top frame.
  51.      */
  52.  
  53.     WindowBarCurrent( TOP, NULL );
  54.     SetButton( NULL, WHITE, NULL );
  55.     DrawAt( 300, 120 );
  56.     AttachDialog("Options", NULL, 
  57.         "Scramble;Size|@(Easy|03;The Famous 4 x 4|04;Hard|05;Very Hard|06;You've got to be Kidding|10)^R",
  58.         NULL, "MD", NULL, NULL); 
  59.     DrawButton( "Options", NULL, "Ns;D", "op");
  60.     Draw();
  61.     WindowBarCurrent( NULL, NULL );
  62.  
  63.     load_icon( "/windows/apps/puzzle" );
  64.  
  65.     DrawStart(NULL, 0);
  66.  
  67.     while ( go )
  68.         {
  69.         GetEvent ( 0, &msg, sizeof(msg));
  70.  
  71.         switch ( Event ( &msg ) )
  72.             {
  73.             case QUIT:
  74.                 WindowClose( 0, NULL );
  75.                 go = NO;
  76.                 break;
  77.  
  78.             case TERMINATED:
  79.                 go = NO;
  80.                 break;
  81.  
  82.             case CLICK:
  83.                 if (msg.hdr.code == 'S') {
  84.                     /* game piece selected */è                    move(atoi(msg.hdr.key) - 1);
  85.                     mv++;
  86.                     win ();
  87.                     }
  88.  
  89.                 break;
  90.  
  91.             case DIALOG:
  92.                 switch(CASE(msg.hdr.key)) {
  93.                 case '03': case '04': case '05': case '06':
  94.                    case '07': case '10':
  95.                     rows = atoi(msg.hdr.key);
  96.                 case 'Sc':
  97.                     new_game();
  98.                 break;
  99.                 }
  100.             }
  101.         }
  102.  
  103.     GraphicsClose( );
  104.     exit (0);
  105.     }
  106.  
  107. init() {
  108.     int    i, j, r, loop;
  109.  
  110.     max_num = rows*rows;
  111.  
  112.     for (i = 0; i < rows; i++)
  113.         for (j = 0; j < rows; j++) {
  114.             b[i][j] = ( i * rows + j);
  115.             old[i][j] = -1;
  116.             }
  117.  
  118.     i = j = rows - 1;
  119.     srand(get_ticks());
  120.     r = rand() % 200 + 500;
  121.  
  122.     for (loop = 0; loop < 5000; ++loop) {
  123.         switch (rand() % 4) {
  124.         case 0:
  125.             if (i != 0) {
  126.                 b[i][j] = b[i - 1][j];
  127.                 b[i - 1][j] = max_num;
  128.                 --i;
  129.                 }
  130.             break;
  131.  
  132.         case 1:
  133.             if (i != rows - 1) {
  134.                 b[i][j] = b[i + 1][j];
  135.                 b[i + 1][j] = max_num;
  136.                 i++;
  137.                 }
  138.             break;
  139. è        case 2:
  140.             if (j != 0) {
  141.                 b[i][j] = b[i][j - 1];
  142.                 b[i][j - 1] = max_num;
  143.                 --j;
  144.                 }
  145.             break;
  146.  
  147.         case 3:
  148.             if (j != rows - 1) {
  149.                 b[i][j] = b[i][j + 1];
  150.                 b[i][j + 1] = max_num;
  151.                 j++;
  152.                 }
  153.             break;
  154.             }
  155.         }
  156.     }
  157.  
  158.  
  159.  
  160. display() {
  161.     int    i, j;
  162.  
  163.     for (i = 0; i < rows; i++)
  164.         if (memcmp(b[i], old[i], rows)) {
  165.             for (j = 0; j < rows; j++)
  166.                 if (b[i][j] != max_num)
  167.                     draw_number(i, j, b[i][j] + 1);
  168.             memcpy(old[i], b[i], rows);
  169.             }
  170.     }
  171.  
  172.  
  173. draw_number( row, col, number)
  174. int row, col, number;
  175.     {
  176.     char tbuf[4];
  177.  
  178.     tsprintf(tbuf, "%2d", number);
  179.         
  180.     SetColor ( "T", BLACK );
  181.  
  182.     DrawAt (PANE_BORDER + (row*RECT_HEIGHT) + CHARH/2,
  183.             PANE_BORDER + (col*RECT_WIDTH ));
  184.  
  185.     DrawText( tbuf, 0, 0, 0, "Sem", tbuf);
  186.  
  187.     Draw ( );
  188.     }
  189.  
  190.  
  191.  
  192.  
  193. move_number( row, col, number)èint row, col, number;
  194.     {
  195.     char buffer[7];
  196.  
  197.     tsprintf(buffer, "%2d", number);
  198.     ShiftTo( buffer,     PANE_BORDER + (row*RECT_HEIGHT) + CHARH/2,
  199.                         PANE_BORDER + (col*RECT_WIDTH ));
  200.     }
  201.  
  202.  
  203.  
  204. move(m)
  205. int m;
  206.     {
  207.     int    i1, j1, i, j, i2, j2, c;
  208.  
  209.     i1 = j1 = -1;
  210.  
  211.     for (i = 0; i1 == -1 && i < rows; i++)
  212.         for (j = 0; j < rows; j++)
  213.             if (b[i][j] == m) {
  214.                 i1 = i;
  215.                 j1 = j;
  216.                 break;
  217.                 }
  218.  
  219.     if (i1 != -1) {
  220.         i2 = j2 = -1;
  221.         for (i = 0; i < rows; i++)
  222.             if (b[i][j1] == max_num) {
  223.                 i2 = i;
  224.                 j2 = j1;
  225.                 break;
  226.                 }
  227.         if (i2 == -1)
  228.             for (j = 0; j < rows; j++)
  229.                 if (b[i1][j] == max_num) {
  230.                     i2 = i1;
  231.                     j2 = j;
  232.                     break;
  233.                     }
  234.         if (i2 == -1)
  235.             return;
  236.         }
  237.     else
  238.         return;
  239.  
  240.     /* Hold picture for smoother updates */
  241.     PictureHold( );
  242.  
  243.     if (i1 == i2)
  244.         if (j1 < j2)
  245.             for (j = j2 - 1; j >= j1; --j) {
  246.                 b[i1][j + 1] = b[i1][j];
  247.                 move_number(i1, j+1, b[i1][j]+1);è                }
  248.         else
  249.             for (j = j2; j < j1; j++) {
  250.                 b[i1][j] = b[i1][j + 1];
  251.                 move_number(i1, j, b[i1][j+1]+1);
  252.                 }
  253.     else
  254.         if (i1 < i2)
  255.             for (i = i2 - 1; i >= i1; --i) {
  256.                 b[i + 1][j1] = b[i][j1];
  257.                 move_number(i+1, j1, b[i][j1]+1);
  258.                 }
  259.         else
  260.             for (i = i2; i < i1; i++) {
  261.                 b[i][j1] = b[i + 1][j1];
  262.                 move_number(i, j1, b[i+1][j1]+1);
  263.                 }
  264.     b[i1][j1] = max_num;
  265.  
  266.     /* update current picture */
  267.     PictureContinue( );
  268.     }
  269.  
  270.  
  271.  
  272. win() {
  273.     int    c = 0, i, j;
  274.     char buf[50];
  275.  
  276.     for (i = 0; i < rows; i++)
  277.         for (j = 0; j < rows; j++)
  278.             if (b[i][j] < c)
  279.                 return( 0 );
  280.             else
  281.                 c = (int) b[i][j];
  282.  
  283.     tsprintf(buf, "You got it in %d moves!", mv);
  284.     Notice( NULL, "You Win", NULL, "W", buf);
  285.  
  286.     return( 1 );
  287.     }
  288.  
  289.  
  290. new_game() {
  291.     RECT_AREA area;
  292.  
  293.     WindowInfo(NULL,&area,NULL,NULL,NULL,NULL);
  294.  
  295.     /* erase all elements in the picture */
  296.     WindowHold( );
  297.     Erase( ALL );
  298.  
  299.     area.height = PANE_HEIGHT;
  300.     area.width  = PANE_WIDTH;
  301. è    init( );
  302.     display( );
  303.     mv = 0;
  304.  
  305.     WindowChange( &area, NULL, KEEP, NULL, "!" );
  306.     WindowContinue( );
  307.     }
  308.  
  309.